package mathwork;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Vector;

import FPlot.FPlot;

public class Mathwork {

	static public boolean ifplot=false;
	static public Poly lsm1(Vector<Double>x,Vector<Double>y){
		return Mathwork.lsm1(x, y, "lsm1");
	}
	static NormalDistributionTable table=new NormalDistributionTable();
	
	static public Poly lsm1(Vector<Double>x,Vector<Double>y,String plottitle){
		Poly result=new Poly();
		
		if(x.size()!=y.size() || x.size()<1){
			return null;
		}
		

		Double meanx=mean(x);
		Double meany=mean(y);
		Double Sxy=cov(x,y,false);
		Double Sx=cov(x,false);
		Double a=Sxy/Sx;
		Double b=meany-a*meanx;
			
		result.add(b);
		result.add(a);
		
		/*寄与率*/
		Vector <Double> esty=new Vector<Double>();
		Iterator<Double> it=x.iterator();
		while(it.hasNext()){
			Double tmp=it.next();
			esty.add(result.PolyValue(tmp));
		}
			
		result.SetlsmR(Mathwork.lsmR(esty, y));
		
		if(Mathwork.ifplot){
			FPlot plot=new FPlot(plottitle+"("+Mathwork.Roundup(result.GetlsmR(),2)+")");
			plot.Add(x, y, "orig", true);
			plot.Add(x, esty, "estimated", false);
			plot.show();			
		}
		
		return result;
	}
	
	static public Double lsmR(Vector<Double>esty,Vector<Double>orgy){
		return Mathwork.cov(esty, true)/Mathwork.cov(orgy, true);
	}
	
	static public Double cov(Vector<Double>x, boolean issample){
		Double result=0.0;
		Double meanx=mean(x);
		int i;
		
		if(x.size()<1){
			return null;
		}
		
		if(x.size()==1)
			return 0.0;
		
		for(i=0;i<x.size();i++){
			result+=Math.pow(x.elementAt(i)-meanx, 2);
		}
		
		if(issample){
			return result/(x.size()-1);
		}else{
			return result/(x.size());
		}
	}
	
	static public Double cov(Vector<Double>x,Vector<Double>y,boolean issample){
		Double result=0.0;
		Double meanx=mean(x);
		Double meany=mean(y);
		int i;
		
		if(x.size()!=y.size() || x.size()<1 ){
			return null;
		}
		
		for(i=0;i<x.size();i++){
			result+=(x.elementAt(i)-meanx)*(y.elementAt(i)-meany);
		}
		
		if(issample){
			return result/(x.size()-1);
		}else{
			return result/(x.size());
		}
	}
	
	static public Double std(Vector<Double>x){
		return Math.sqrt(cov(x,true));
	}
	
	static public Double mean(Vector<Double>x){
		Double result=0.0;
		int i;
		for(i=0;i<x.size();i++){
			result+=x.elementAt(i);
		}
		
		return result/x.size();
	}

	/*lagrange interpolate
	 * 1. x.size=y.size
	 * 2. xi!=xj
	 * */
	static public Double lagrange(Vector<Double>x,Vector<Double>f, Double newx){
		Double result=0.0;
		int i,j;
		if(x.size()!=f.size() || x.size()<1)
			return null;
		
		for(i=0;i<x.size();i++){
			Double g=1.0;
			for(j=0;j<x.size();j++){
				if(i!=j){
					g*=(newx-x.elementAt(j))/(x.elementAt(i)-x.elementAt(j));
				}
			}
			result+=g*f.elementAt(i);
		}
		return result;
	}
	
	static public Vector<Double> standardize(Vector<Double>x){
		Vector<Double> result=new Vector<Double>();
		Double stdval=0.0;
		Double meanval=0.0;
		int i;
		if(x.size()<1)
			return null;
		
		stdval=Mathwork.std(x);
		meanval=Mathwork.mean(x);
		for(i=0;i<x.size();i++){
			result.add((x.elementAt(i)-meanval)/stdval);
		}
		
		return result;
	}
	
	static public Double corrcoef(Vector<Double>x,Vector<Double>y){
		/*相関係数*/
		Double result=0.0;
		result=cov(x,y,true)/(std(x)*std(y));
		return result;
				
	}
	
	static public Double Roundup(Double val,Integer bit){
		BigDecimal bi=new BigDecimal(val);
		return bi.setScale(bit, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	static public Vector<Double> lognormlize(Vector<Double> x){
		Vector<Double> result=new Vector<Double>();
		int i;
		for(i=0;i<x.size();i++){
			if(x.elementAt(i)!=0.0){
				result.add(Math.log(Math.abs(x.elementAt(i))));
			}else{
				result.add(Math.log(0.01));
			}
		}
		return result;
	}
	
	static public Vector<Double> lognormalest(Vector<Double> x,Double percent){
		Vector<Double> result=new Vector<Double>();
		Vector<Double> logx=Mathwork.lognormlize(x);
		Double meanlogx=Mathwork.mean(logx);
		Double deltalogx=Mathwork.std(logx);
		
		Double z=table.FastGetZ(percent);
		Double logresulth=meanlogx+z*deltalogx;
		Double logresultl=meanlogx-z*deltalogx;
		
		result.add(Mathwork.Roundup(Math.exp(logresulth), 2));
		result.add(Mathwork.Roundup(Math.exp(logresultl), 2));
		return result;
	}
	
	static public Vector<Vector<Double>> plusminus(Vector<Double>x){
		Vector<Vector <Double>> result=new Vector<Vector<Double>>();
		Vector<Double> plus=new Vector<Double>();
		Vector<Double> minus=new Vector<Double>();
		int i;
		Double sum=0.0;
		int minusflag=0;
		for(i=0;i<x.size();i++){
			if(x.elementAt(i).compareTo(0.0)>=0){
				if(minusflag==0){
					sum+=x.elementAt(i);	
				}else{
					minus.add(Mathwork.Roundup(sum, 2));
					sum=0.0;
					minusflag=0;
					sum+=x.elementAt(i);
				}
			}else{
				if(minusflag==0){
					if(i!=0){
						plus.add(Mathwork.Roundup(sum, 2));
					}
					sum=0.0;
					minusflag=1;
					sum+=x.elementAt(i);
				}else{
					sum+=x.elementAt(i);	
				}
			}
		}
		if(sum.compareTo(0.0)>=0){
			plus.add(Mathwork.Roundup(sum, 2));
		}else{
			minus.add(Mathwork.Roundup(sum, 2));
		}
		
		result.add(plus);
		result.add(minus);
		return result;
	}
	
	static public Double lastplusminus(Vector<Double>x){
		Double sum;
		int i;
		if(x==null || x.isEmpty()){
				return 0.0;
		}
		
		sum=x.lastElement();
		for(i=x.size()-2;i>=0;i--){
			if(((sum.compareTo(0.0)>=0)&&(x.elementAt(i).compareTo(0.0)>=0))||
			   ((sum.compareTo(0.0)<0)&&(x.elementAt(i).compareTo(0.0)<0))){
				sum+=x.elementAt(i);
			}else{
				break;
			}
		}
		
		return sum;
		
	}
	
}

